import React, {
  MutableRefObject,
  useCallback,
  useContext,
  useEffect,
  useMemo,
  useReducer,
  useRef,
  useState,
} from 'react';
import { TextWidget, getMessage, useTreeNode } from '@inbiz/react';
import {
  Button,
  Checkbox,
  ConfigProvider,
  message,
  PaginationProps,
  Row,
  Space,
} from 'antd';
import { CaretDownOutlined, MenuOutlined, CaretUpOutlined } from '@ant-design/icons';
import { ColumnsType, ColumnType, FilterValue } from 'antd/lib/table/interface';
import cls from 'classnames';
import { hasAuth } from '@inbiz/basic/AuthForm';
import { customRequest, useInbizData } from '@inbiz/hooks';
import { InbizIcon, uuid, request, multilingualFormat } from '@inbiz/utils';
import { IPageInbiz } from '@inbiz/core/lib/sdk/inbiz';
import {
  SortableContainer,
  SortableElement,
  SortableHandle,
} from 'react-sortable-hoc';
import { arrayMoveImmutable } from 'array-move';
import {
  ActionEnum,
  arrIsEmpty,
  builtInTmpl,
  cardTmplModules,
  ColumnConst,
  EventsMap,
  InlineDefaultActions,
  ResConst,
  UnitEnum,
} from './shared';
import {
  ActionConfigType,
  ActionProps,
  ModalConfig,
  PageData,
  PropConfigType,
  QueryParams,
  RecordType,
  TitleConfig,
  ToolbarType,
  VisibleColumnType,
} from './interfaces';
import { InBizTableCtx, InBizTableRefCtx } from './context';
import Actions from './preview/web/Actions';
import { useReactToPrint } from 'react-to-print';
import { TmplType } from './designer/web/CardTmplSelect';
import formatters from './formatters';
import tableApi from './preview/web/serviceApi';
import { getSearchValues, treeToArray } from './util';

/**
 * 分页hook：初始化一些参数
 * @param config antd 表格配置属性
 */
export const usePagination = (config: PaginationProps): PaginationProps => {
  return {
    current: 1,
    pageSize: 30,
    defaultPageSize: 10,
    defaultCurrent: 1,
    showSizeChanger: true,
    showTotal: (total: number) =>
      `${getMessage('Table.common')} ${total} ${getMessage('Table.strip')}`,
    ...config,
  };
};

/**
 * 平铺表格配置属性
 */
export const useColumnConfig = () => {
  const { columnConfig, thumbConfig, previewMode, inbiz } = useContext(InBizTableCtx);
  const { tableValues, formItems = {}, queryFields = [], auth } = columnConfig || {};
  const { attrs, actions = [], subWindow = [] } = tableValues || {};
  const { tableValues: thumbValues, formItems: thumbFormItems = {} } = thumbConfig || {};
  const { attrs: thumbAttrs } = thumbValues || {};
  return {
    formItems,
    attrs,
    thumbAttrs,
    thumbFormItems,
    actions: previewMode ? actions.filter(action => action.actionType == 'custom' || action.actionType == 'customColumn') : actions,
    subWindow,
    queryFields,
    auth,
    inbiz,
  };
};
/**
 * 解析自定义卡片模板
 */
export const useCardTmpl = (cardTmpl: TmplType) => {
  const [loading, setLoading] = useState(false);
  const tmplNodeRef = useRef(cardTmpl);
  const builtInTmplArr = Object.keys(builtInTmpl);
  const getCardTmpl = () => {
    if (!cardTmpl?.id || builtInTmplArr.includes(cardTmpl?.id)) {
      return;
    }
    setLoading(true);
    request
      .get(cardTmpl.id)
      .then((script: string) => {
        if (script) {
          const tmpl = {} as TmplType;
          new Function('exports', 'React', 'require', script)(
            tmpl,
            React,
            (moduleName: string) => cardTmplModules[moduleName],
          );
          tmplNodeRef.current = tmpl;
        }
      })
      .finally(() => setLoading(false));
  };

  useEffect(() => {
    getCardTmpl();
  }, []);

  return {
    tmplNode: {
      id: cardTmpl?.id,
      node: tmplNodeRef.current,
    },
    tmplLoading: loading,
  };
};

/**
 * 获取表格配置
 */
export const useFormItems = () => {
  const { formItems = {} } = useColumnConfig();
  return formItems;
};

/**
 * 处理表头操作按钮配置
 */
export const useToolbar = (): ToolbarType | undefined => {
  const { columnConfig, previewMode } = useContext(InBizTableCtx);
  const { tableValues, formItems = {} } = columnConfig || {};
  const { actions } = tableValues || {};
  return useMemo(() => {
    if (arrIsEmpty(actions)) {
      return;
    }
    const buttons = (actions as ActionProps[])?.filter((action) => {
      if (action.actionType === ActionEnum.customColumn) {
        return false;
      }
      if (previewMode && action.actionType !== ActionEnum.custom) {
        return false;
      }
      if (
        (action.position === 'tableHeader' && !InlineDefaultActions.includes(action.actionType)) ||
        (!action.position &&
          !InlineDefaultActions.includes(action.actionType) &&
          action.actionType !== ActionEnum.del)
      ) {
        if (
          action.actionType &&
          [ActionEnum.save, ActionEnum.add, ActionEnum.saveAndNew].includes(
            action.actionType as ActionEnum,
          )
        ) {
          action.buttonType = 'primary';
        }
        return true;
      }
      return false;
    });
    return {
      actions: buttons,
      displayQty: 99,
      inLineBtnShow: formItems?.inLineBtnShow,
      tableHeaderBtnShow: formItems?.tableHeaderBtnShow,
    };
  }, [actions, previewMode, formItems]);
};

/**
 * 处理弹窗配置
 */
export const useModalConfig = (): ModalConfig => {
  const { actions, subWindow, formItems } = useColumnConfig();

  return useMemo(() => {
    const { width, maxHeight, minHeight } = formItems || {};
    const { widowWidth = 60, widthSuffix = '%' } = width || {};
    const { height = 60, suffix = '%' } = maxHeight || {};
    const { height: windowHeight = 60, suffix: heightSuffix = '%' } = minHeight || {};
    const modalWidth = widthSuffix === '%' ? `${widowWidth}${widthSuffix}` : widowWidth;
    const modalMaxHeight = suffix === '%' ? `${height}${suffix}` : height;
    const modalMinHeight = heightSuffix === '%' ? `${windowHeight}${heightSuffix}` : windowHeight;
    const actionObj =
      actions?.reduce((obj, cur) => {
        if (cur) {
          obj[cur.actionType] = cur;
        }
        return obj;
      }, {}) || {};
    return {
      actions: (subWindow as ActionConfigType[])?.map((subAction) => {
        const parent = subAction?.parentAction ? actionObj?.[subAction?.parentAction] : null;
        if (!parent) {
          return subAction;
        }
        return {
          ...subAction,
          page: parent.page,
          windowName: parent.windowName || parent.actionName,
          openMode: parent.openMode,
        };
      }),
      width: modalWidth,
      maxHeight: modalMaxHeight,
      minHeight: modalMinHeight,
    };
  }, [subWindow, actions, formItems]);
};

/**
 * 获取表格列总宽度
 * @param columns 表格列
 */
export const useColumnsWidth = (columns?: ColumnsType<RecordType>) => {
  return useMemo(
    () =>
      columns?.reduce((sum, col) => {
        if (col.width) {
          return sum + (col.width as number);
        }
        return sum;
      }, 0) || 0,
    [columns],
  );
};

export const percentageWidthCount = (params: {
  tableWidth: number;
  rowSelection: any;
  columns: ColumnsType<RecordType>;
  dragSort?: boolean;
  height?: number;
  showLineNumber?: boolean
}) => {
  const { tableWidth, rowSelection, columns, dragSort = false, height = 0 } = params;
  const fixedColumn = [ColumnConst.index, ColumnConst.sort, ColumnConst.actions];
  let totalWidth = rowSelection ? tableWidth - 50 : tableWidth - 0;
  totalWidth = dragSort ? totalWidth - 50 : totalWidth;
  if (params.showLineNumber) {
    totalWidth -= 50;
  }
  // 百分比情况下，如果设置了表格固定高度，需要减去滚动条的宽度和表格的本身border 6 + 2
  totalWidth = height ? totalWidth - 8 : totalWidth;
  const actionCol = columns!.find(
    (column: ColumnType<RecordType>) => column.dataIndex === ColumnConst.actions,
  );
  let attrsWidth = 0;
  columns!.forEach((column: ColumnType<RecordType>) => {
    if (!fixedColumn.includes(column.dataIndex)) {
      attrsWidth += Number(column.width);
    }
  });
  return columns!.map((column: ColumnType<RecordType>) => {
    column.fixed = undefined;
    if (fixedColumn.includes(column.dataIndex)) {
      return column;
    }
    const width = Math.floor(
      ((actionCol ? totalWidth - Number(actionCol.width) : (totalWidth as number)) / attrsWidth) *
      Number(column.width),
    );
    return {
      ...column,
      width: width < 50 ? 50 : width,
    };
  });
};

/**
 * 处理表格在百分比和像素下的列宽度
 * @param tableWidth 表格总宽度
 * @param totalWidth 表格列总宽度
 * @param columns 表格列
 */
export const useColumns = (
  tableWidth: number,
  totalWidth: number,
  columns: ColumnsType<RecordType>,
  pageData?: any,
  height?: number,
) => {
  const { rowSelection, dragSort, showLineNumber } = useContext(InBizTableCtx);
  const { widthUnit: unit } = useFormItems();
  return useMemo(() => {
    if (!columns) {
      return [];
    }
    columns.forEach((column) => {
      if (column.filter) {
        const filters =
          pageData?.data
            ?.map((item) => {
              return {
                text: item[column.dataIndex],
                value: item[column.dataIndex],
              };
            })
            ?.filter(
              (item, index, selfArr) =>
                selfArr.findIndex((el) => el.value === item.value) === index,
            ) || [];
        filters.forEach((item) => {
          const num = pageData?.data?.filter(
            (data) => data[column.dataIndex] === item.value,
          ).length;
          if (num > 1) {
            item.text = `${item.text}(${num})`;
          }
        });
        column.filters = filters || [];
        column.filterSearch = (input: string, record: any) => {
          const data = input.trim().split(' ');
          let result: boolean = false;
          data.forEach((item) => {
            if (record.value.toString().includes(item)) {
              result = true;
            }
          });
          return result;
        };
        column.onFilter = (value, record) => {
          return record[column.dataIndex].toString() === value;
        };
      }
    });
    const actionCol = columns.find(
      (column: ColumnType<RecordType>) => column.dataIndex === ColumnConst.actions,
    );
    if (unit === UnitEnum.percentage) {
      return percentageWidthCount({ tableWidth, rowSelection, dragSort, columns, height, showLineNumber });
    }
    if (actionCol && totalWidth <= tableWidth) {
      actionCol.width = (actionCol.fixed as string) === 'none' ? undefined : actionCol.width;
      if (columns.length > 2 && actionCol.width) {
        const lastColIdx = actionCol.fixed === 'right' ? columns.length - 2 : columns.length - 1;
        columns[lastColIdx].width = undefined;
      }
    }
    // 为像素时，如果没有操作列，则最后一列为自适应宽度，不设置具体宽度
    if (!actionCol && columns?.[columns.length - 1]) {
      columns[columns.length - 1].width = undefined;
    }
    return columns;
  }, [tableWidth, pageData?.data, columns]);
};

/**
 * 判断是否为设计器模式下
 */
export const useIsDesigner = () => {
  return !!useTreeNode();
};

/**
 * 初始化查询分页参数
 */
export const useInitSearchRef = () => {
  const { searchRef } = useContext(InBizTableRefCtx);
  const formItems = useFormItems();
  useMemo(() => {
    searchRef.current = {
      ...searchRef.current,
      iConditions: {
        ...(searchRef.current?.iConditions ?? {}),
        pageSize: formItems.pageSize || 30,
        pageIndex: 1,
      },
      pageInfo: {
        current: 1,
        pageSize: formItems.pageSize || 30,
      },
    };
  }, []);
};

/**
 * 设置表格横向滚动
 * @param tableWidth
 * @param totalWidth
 */
export const useScrollX = (tableWidth: number, totalWidth: number) => {
  const { widthUnit: unit, actionColumnWidth = 200 } = useFormItems();
  return useMemo(
    () =>
      unit === UnitEnum.pixel && totalWidth > tableWidth
        ? `${totalWidth + actionColumnWidth}px`
        : undefined,
    [tableWidth, totalWidth],
  );
};

/**
 *
 * @param pagination
 * @param columns
 */
export const useIndex = (
  pagination: { currentPage: number; pageSize: number },
  columns?: ColumnsType<RecordType>,
) => {
  return useMemo(() => {
    if (arrIsEmpty(columns)) {
      return;
    }
    const index = columns?.find(
      (col) => (col as ColumnType<RecordType>).dataIndex === ColumnConst.index,
    );
    if (!index) {
      return;
    }
    index.render = (text, record, rowIdx) => {
      return (
        pagination.currentPage &&
        `${rowIdx + 1 + (pagination.currentPage - 1) * (pagination.pageSize || 10)}`
      );
    };
  }, []);
};

/**
 * 格式化导出字段
 */
export const useExportFields = () => {
  const { attrs, thumbAttrs } = useColumnConfig();
  const { tableViewType, showPageType } = useContext(InBizTableCtx);
  // 判断是否为卡片视图或开启并切换成缩略图
  if (tableViewType === 'card' || showPageType === 'thumbnail') {
    let _attrs = attrs;
    if (showPageType === 'thumbnail') {
      _attrs = thumbAttrs;
    }
    const data =
      _attrs?.filter((col) => {
        if (col.typeValue == 'array') {
          return !!col.children?.length;
        }
        return col?.propName && col.propName != '';
      }) || [];
    const _data = treeToArray(data);
    return _data.map((col: any) => {
      return {
        colName: col.label,
        proName: col.propName,
      };
    });
  }
  return attrs
    ?.filter((col: PropConfigType) => (col as VisibleColumnType).visible !== '0' && col.width)
    .map((col: any) => {
      return {
        colName: getMessage(col.columnName),
        proName: col.propName,
      };
    });
};

/**
 * 获取appid
 */
export const useAppId = () => {
  const { inbiz } = useContext(InBizTableCtx);
  return inbiz?.appInfo?.appId;
};

/**
 * 拖拽改变列宽
 * @param columns
 * @param handleResize
 */
export const useResize = (
  columns: ColumnType<RecordType>[],
  handleResize: (idx: number) => (e: any, { size }: any) => void,
) => {
  const { resizeColumnWidth } = useContext(InBizTableCtx);
  if (columns && resizeColumnWidth) {
    columns.map((column, index) => {
      column.onHeaderCell = (col: ColumnType<RecordType>) => {
        return {
          dataIndex: col.dataIndex,
          width: col.width,
          onResize: handleResize(index),
          columns: columns,
        };
      };
    });
  }
};

/**
 * 按钮聚合操作
 * @param handlePrint
 * @param tableCacheRef
 * @param modalRef
 */
export const useActionReducer = ({
  handlePrint,
  tableCacheRef,
  modalRef,
  importModalRef,
  exportModalRef,
}: {
  attrs?: PropConfigType[];
  tableCacheRef: MutableRefObject<any>;
  importModalRef?: MutableRefObject<any>;
  exportModalRef?: MutableRefObject<any>;
  modalRef: MutableRefObject<any>;
  handlePrint: () => void;
}) => {
  const {
    emit,
    inbiz,
    modelname,
    selectComponent = '',
    relationField = '',
    primarykey
  } = useContext(InBizTableCtx);
  const { eventsRef, pageRef, searchRef, tableTopRef } = useContext(InBizTableRefCtx);
  const appId = useAppId();
  const { formItems, queryFields } = useColumnConfig();
  let row = {};
  let key = '';
  const onSave = useCallback(async () => {
    if (selectComponent) {
      row = (inbiz && inbiz(selectComponent).getClickRow()) ?? {};
      key = (inbiz && inbiz(selectComponent).getPrimaryKey()) ?? 'id';
      return pageRef.current!.page.submit({
        [relationField]: row[key],
        isRelation: true,
      });
    }
    return pageRef.current!.page.submit(false);
  }, []);
  const getTotalPage = () => {
    const { pageSize } = tableCacheRef.current.pageInfo || {};
    const total = tableCacheRef.current.total;
    return total % pageSize === 0 ? total / pageSize : Math.ceil(total / pageSize);
  };
  const getPageInfo = (delCounts: number) => {
    const { current, pageSize } = tableCacheRef.current.pageInfo || {};
    const total = tableCacheRef.current.total;
    if (
      current !== 1 &&
      current === getTotalPage() &&
      delCounts === (total % pageSize ? total % pageSize : delCounts)
    ) {
      return {
        pageInfo: {
          current: current - 1,
        },
        iConditions: {
          pageIndex: current - 1
        }
      };
    }
    return;
  };
  const getRow = (dataSource: RecordType[], id: number, isPre?: boolean) => {
    if (!dataSource) {
      return;
    }
    const curInx = dataSource.findIndex((row) => row?.[primarykey] == id);
    return dataSource[isPre ? curInx - 1 : curInx + 1];
  };
  const reducer = useCallback(async (state: any, action: any): Promise<any> => {
    const { actionType, parentType } = action;
    const needPage = [
      ActionEnum.add,
      ActionEnum.edit,
      ActionEnum.view,
      ActionEnum.saveAndNew,
      ActionEnum.pre,
      ActionEnum.next,
    ];
    if (needPage.includes(actionType) && parentType !== ActionEnum.custom) {
      action['title'] = action.windowName || action.actionName;
      action['page'] = formItems?.pageSelect || action?.page;
    }
    if (needPage.includes(action.actionType) && !(action.page as ActionEnum)) {
      message.warning(getMessage('Table.tips.pleaseBindThePage'));
      return;
    }
    if (
      [ActionEnum.add, ActionEnum.edit, ActionEnum.del, ActionEnum.thoroughDel].includes(actionType)
    ) {
      const result =
        (await eventsRef?.current.onBeforeOperationAsync?.(actionType, action?.data)) ?? true;
      if (!result) {
        return ResConst.other;
      }
    }
    switch (actionType) {
      case ActionEnum.add: {
        if (tableCacheRef.current.relationParent || !selectComponent) {
          modalRef.current.showModal(true, {}, action);
        } else {
          message.warning(getMessage('Table.tip.parentRequire'));
        }
        return action;
      }
      case ActionEnum.edit: {
        modalRef.current.showModal(true, {}, action);
        return action;
      }
      case ActionEnum.view: {
        modalRef.current.showModal(true, {}, action);
        return action;
      }
      case ActionEnum.custom: {
        if (action?.page) {
          modalRef.current.showModal(true, {}, action);
          return action;
        }
        return;
      }
      case ActionEnum.save:
        return onSave()
          .then((res) => {
            if (!res) return;
            tableCacheRef.current.loadData(row[key]);
            Promise.resolve(eventsRef?.current.onBeforeClose?.() ?? true).then((res) => {
              if (!res) {
                return;
              }
            });
            modalRef.current.showModal(false);
            return;
          })
          .catch((err: any) => {
            return Promise.reject(err);
          });
      case ActionEnum.saveAndNew: {
        return onSave()
          .then(async (res: any) => {
            if (!res) return;
            tableCacheRef.current.loadData(row[key]);
            return {
              ...action,
              data: {
                id: undefined,
              },
            };
          })
          .catch((err: any) => {
            return Promise.reject(err);
          });
      }
      case ActionEnum.pre: {
        let curRow = (await state)?.data || tableCacheRef.current.currentData;
        const pre = getRow(tableCacheRef.current.data, curRow?.[primarykey], true);
        if (!pre) {
          const { current, pageSize } = tableCacheRef.current.pageInfo || {};
          if (current === 1) {
            message.warning(getMessage('Table.tips.noPreviousData'));
          } else {
            const pageInfo = { current: current - 1, pageSize };
            searchRef.current.pageInfo = pageInfo;
            const nextPageData = await tableCacheRef.current.refresh({ pageInfo });
            curRow = nextPageData?.[nextPageData?.length - 1];
          }
          return {
            ...action,
            data: curRow,
          };
        }
        return {
          ...action,
          data: pre,
        };
      }
      case ActionEnum.next: {
        let curRow = (await state)?.data || tableCacheRef.current.currentData;
        const next = getRow(tableCacheRef.current.data, curRow?.[primarykey], false);
        if (!next) {
          const { current, pageSize } = tableCacheRef.current.pageInfo || {};
          const totalPage = getTotalPage();
          if (current === totalPage) {
            message.warning(getMessage('Table.tips.noNextData'));
          } else {
            const pageInfo = { current: current + 1, pageSize };
            searchRef.current.pageInfo = pageInfo;
            const nextPageData = await tableCacheRef.current.refresh({ pageInfo });
            curRow = nextPageData?.[0];
          }
          return {
            ...action,
            data: curRow,
          };
        }
        return {
          ...action,
          data: next,
        };
      }
      case ActionEnum.del: {
        const primaryKey = tableCacheRef.current.primaryKey;
        const row = (inbiz && inbiz(selectComponent)?.getClickRow?.()) ?? {};
        if (!action.data?.[primaryKey] && arrIsEmpty(tableCacheRef.current.keyList)) {
          message.warning(getMessage('Table.tips.pleaseSelectTheDataToBeDeleted'));
          return ResConst.other;
        }
        //@ts-ignore
        const ids = action.data?.[primaryKey]
          ? [action.data?.[primaryKey]]
          : tableCacheRef.current.keyList;
        let resData: any;
        if (action?.api) {
          const request = customRequest(action.api as any, inbiz);
          if (action.api['url']) {
            resData = await request(action?.data);
          } else {
            resData = await request({
              appId: appId,
              key: action.api?.modelKey,
              id: action?.data?.[primaryKey],
              iConditions: {
                ...action?.data,
              },
            });
          }
        } else {
          resData = await inbiz?.submit({
            modleName: modelname,
            data: ids.map((ele: string) => ({ id: ele, _opt: 'del' })),
            noRelation: true,
          });
        }
        if (!resData) return;
        message.success(getMessage('Table.tips.deleteSucceeded'));
        const pageInfo = getPageInfo(ids.length);
        tableCacheRef.current.loadData(row?.[primaryKey], pageInfo);
        if (pageInfo?.pageInfo.current) {
          searchRef.current.pageInfo.current = pageInfo?.pageInfo.current || 1;
        }
        (emit as any)?.(EventsMap.onDelete, action?.data);
        tableCacheRef?.current?.setSelect?.([]);
        return;
      }
      case ActionEnum.thoroughDel: {
        const primaryKey = tableCacheRef.current.primaryKey;
        const row = (inbiz && inbiz(selectComponent)?.getClickRow?.()) ?? {};
        if (!action.data?.[primaryKey] && arrIsEmpty(tableCacheRef.current.keyList)) {
          message.warning(getMessage('Table.tips.pleaseSelectTheDataToBeDeleted'));
          return ResConst.other;
        }
        const ids = action.data?.[primaryKey]
          ? [action.data?.[primaryKey]]
          : tableCacheRef.current.keyList;
        return inbiz
          ?.submit({
            modleName: modelname,
            data: ids.map((ele: string) => ({ id: ele, _opt: 'del' })),
            noRelation: true,
            isThoroughDel: true,
          })
          .then((res) => {
            if (!res) return;
            message.success(getMessage('Table.tips.deleteSucceeded'));
            const pageInfo = getPageInfo(ids.length);
            tableCacheRef.current.loadData(row?.[primaryKey], pageInfo);
            if (pageInfo?.pageInfo.current) {
              searchRef.current.pageInfo.current = pageInfo?.pageInfo.current || 1;
            }
            (emit as any)?.(EventsMap.onDelete, action?.data);
            tableCacheRef?.current?.setSelect?.([]);
          })
          .catch();
      }
      case ActionEnum.recovery: {
        const primaryKey = tableCacheRef.current.primaryKey;
        const row = (inbiz && inbiz(selectComponent)?.getClickRow?.()) ?? {};
        if (!action.data?.[primaryKey] && arrIsEmpty(tableCacheRef.current.keyList)) {
          message.warning(getMessage('Table.tips.pleaseSelectTheDataToBeRecovery'));
          return ResConst.other;
        }
        const ids = action.data?.[primaryKey]
          ? [action.data?.[primaryKey]]
          : tableCacheRef.current.keyList;
        return inbiz
          ?.submit({
            modleName: modelname,
            data: ids.toString(),
            noRelation: true,
            isRecoveryData: true,
          })
          .then((res) => {
            if (!res) return;
            message.success(getMessage('Table.tips.successfullyRecovery'));
            const pageInfo = getPageInfo(ids.length);
            tableCacheRef.current.loadData(row?.[primaryKey], pageInfo);
            tableCacheRef.current.setSelect([]);
            if (pageInfo?.pageInfo.current) {
              searchRef.current.pageInfo.current = pageInfo?.pageInfo.current || 1;
            }
          })
          .catch();
      }
      // case ActionEnum.custom: {
      //   break;
      // }
      case ActionEnum.cancel: {
        modalRef.current.showModal(false);
        return;
      }
      case ActionEnum.print: {
        handlePrint();
        return;
      }
      case ActionEnum.import: {
        importModalRef?.current.showModal(true);
        return;
      }
      case ActionEnum.export: {
        exportModalRef?.current.showModal(true);
        return;
      }
      case ActionEnum.query: {
        modalRef.current.showModal(true, {}, action);
        return action;
      }
      case ActionEnum.reset: {
        action.pageRef.current.page.reset();
        tableTopRef.current?.onReset?.();
        // 获取查询页面中组件对象
        const componentValues = action.pageRef.current.page.getFields();
        getSearchValues({
          inbiz,
          searchRef,
          queryFields,
          components: componentValues
        })
        searchRef.current = {
          ...searchRef.current,
          isQueryClick: false  // 是否为查询按钮触发的搜索，便于设置查询按钮的标记
        }
        tableCacheRef.current.refresh();
        return;
      }
      case ActionEnum.serach: {
        // 获取查询页面中组件对象
        const componentValues = action.pageRef.current.page.getFields();
        getSearchValues({
          inbiz,
          searchRef,
          queryFields,
          components: componentValues
        })
        searchRef.current = {
          ...searchRef.current,
          isQueryClick: true  // 是否为查询按钮触发的搜索，便于设置查询按钮的标记
        }
        tableCacheRef.current.refresh();
        modalRef.current.showModal(false);
        return;
      }
    }
  }, []);
  // @ts-ignore

  return useReducer(reducer, undefined);
};

export const useTitle = (title: any) => {
  return useMemo(() => {
    if (typeof title === 'object') {
      return (title as TitleConfig).status ? () => (title as TitleConfig).value : undefined;
    }
    return title;
  }, [title]);
};

export const usePrefixCls = (
  tag?: string,
  props?: {
    prefixCls?: string;
  },
) => {
  const { getPrefixCls } = useContext(ConfigProvider.ConfigContext);
  if (getPrefixCls) {
    return getPrefixCls(tag, props?.prefixCls);
  } else {
    const prefix = props?.prefixCls ?? 'ant-';
    return `${prefix}${tag ?? ''}`;
  }
};

/**
 * 拼接样式inbiz前缀
 * @param tag 组件名字
 *
 */
export const useInbizPrefixCls = (tag?: string, prefixCls?: string) => {
  const prefix = prefixCls ?? 'inbiz-';
  return `${prefix}${tag ?? ''}`;
};

/**
 * 请求数据，拼装参数
 */
export const useFetchData = () => {
  const { emit, sourceModel, primarykey, showPage, sourcetype } = useContext(InBizTableCtx);
  const { searchRef, eventsRef, firstRequestRef } = useContext(InBizTableRefCtx);
  const { runAsync, loading } = useInbizData(
    () => {
      if (sourcetype === 'model') {
        return { modelkey: sourceModel! };
      } else {
        if (typeof sourceModel === 'object') {
          return sourceModel;
        } else {
          return { modelkey: sourceModel! };
        }
      }
    },
    { configEvents: eventsRef },
  );
  const [pageData, setPageData] = useState<PageData>({});
  const appId = useAppId();
  
  // triggerLoad 如果是外部主动触发(load方法)的查询，就不处理参数，直接调查询接口，反之处理查询参数
  const fetchData = useCallback(
    (query?: QueryParams, triggerLoad?: 'outside' | 'inside') => {
      const { pageInfo, orders, conditions, iConditions, sort = false, ...rest } = query || {};
      if ((!sourceModel || !appId) && !eventsRef.current.onRequest) {
        return;
      }
      let _conditions = [];
      if (triggerLoad === 'outside' && conditions.length) {
        _conditions = conditions;
      } else {
        _conditions = formatters.filterCondition(conditions || searchRef.current.conditions);
      }
      let newParam: any = {
        appId: appId,
        key: sourceModel,
        pageInfo: {
          index: pageInfo?.current || searchRef.current.pageInfo!.current,
          size: pageInfo?.pageSize || searchRef.current.pageInfo!.pageSize,
        },
        orderInfo: orders || searchRef.current.orders,
        conditions: formatters.formatFilterCondition(sourcetype!, _conditions),
        iConditions: iConditions ? iConditions : searchRef.current.iConditions,
      };
      const apiParams = {
        index: newParam.pageInfo.index,
        size: newParam.pageInfo.size,
        pageIndex: newParam.pageInfo.index,
        pageSize: newParam.pageInfo.size,
        orderInfo: newParam.orderInfo,
        ...newParam.iConditions,
      };
      if (_conditions) {
        _conditions.forEach((item: { condition: { [key: string]: any }[] }) => {
          item?.condition?.forEach(condition => {
            apiParams[condition.field] = condition.value;
          })
        })
      }
      if (!showPage) {
        newParam.pageInfo = undefined;
      }
      if (sort) {
        newParam = {
          ...newParam,
          ...rest,
        };
        return tableApi.changeDataSort(newParam);
      }
      if (typeof sourceModel == 'object') {
        newParam = apiParams;
      }
      return runAsync(newParam)
        .then((res: any) => {
          const data = res.Rows?.map(({ children, ...restProps }) => {
            return {
              ...restProps,
            };
          });
          setPageData({
            data,
            total: res?.Total,
            primary: primarykey || res?.primary,
            relationField: res?.RelationField,
          });
          if (firstRequestRef.current) {
            (emit as any)?.(EventsMap.onload);
            firstRequestRef.current = false;
          }
          (emit as any)?.(EventsMap.onSuccess, data);
          return data;
        })
        .catch((err) => {
          (emit as any)?.('onError', err.message);
        });
    },
    [primarykey],
  );

  return {
    loading,
    fetchData,
    pageData,
    setPageData,
  };
};

/**
 * 打印
 */
export const usePrint = () => {
  const printTableRef = useRef(null);

  const [printVisible, setPrintVisible] = useState(false);
  const handlePrint = useReactToPrint({
    bodyClass: 'inbiz-table-content-print',
    content: () => printTableRef.current,
    onBeforeGetContent: () => {
      return new Promise((resolve) => {
        setPrintVisible(true);
        resolve({});
      });
    },
    onAfterPrint: () => setPrintVisible(false),
  });
  return {
    printVisible,
    printTableRef,
    handlePrint,
  };
};

/**
 * 格式化表格操作列配置
 */
export const useFormatInnerActions = () => {
  const { actions } = useColumnConfig();

  return (actions as ActionProps[])?.filter((action) => {
    if (action.actionType === ActionEnum.customColumn) {
      return false;
    }
    if (
      action.position === 'inline' ||
      InlineDefaultActions.includes(action.actionType) ||
      (action.position !== 'tableHeader' && action.actionType === ActionEnum.del)
    ) {
      action.buttonType = 'link';
      return true;
    }
    return false;
  });
};

const SortNode = (status, isCurrentColumn) => {
  return (
    <span className="ant-table-column-sorter">
      <span className="ant-table-column-sorter-inner">
        <CaretUpOutlined
          title={getMessage('Table.sort.ascendingOrder')}
          className={cls('ant-table-column-sorter-up', {
            active: status === 'ascend' && isCurrentColumn,
          })}
        />
        <CaretDownOutlined
          title={getMessage('Table.sort.descendingOrder')}
          className={cls('ant-table-column-sorter-down', {
            active: status === 'descend' && isCurrentColumn,
          })}
        />
      </span>
    </span>
  );
};

/**
 * 格式化表格列
 */
export function useFormatColumns(): ColumnsType<RecordType> {
  const { align, showLineNumber, columnResetName, controlId, emit, viewMode } = useContext(InBizTableCtx);
  const { actions, attrs, formItems, auth, inbiz } = useColumnConfig();
  const { eventsRef, searchRef } = useContext(InBizTableRefCtx);
  const innerActions = useFormatInnerActions();
  const [sortFilters, setSortFilters] = useState([]); // 存储排序后的column
  const [changeView, setChangeView] = useState(false); // 解决排序后，点击确定按钮，触发更新，调整columns的顺序
  const changeViewRef = useRef(false); // 记录是否需要更新视图，拖动排序时不更新，点击确定按钮才更新视图
  const sortColumnsRef = useRef([]); // 记录每一次排序的columns，如果有排序就用排序的配置，如果没有排序，就用配置里面的默认配置
  const sortFiltersRef = useRef<any[]>([]); // 解决更新排序后，第二次进入无法更新视图，因为闭包原因
  const guid = inbiz?.appInfo?.userInfo?.guid;
  const page = inbiz?.pageId;
  const tableInfo = getTableStorage();
  const columns = tableInfo?.[guid]?.[page]?.[controlId!]?.columns || [];
  const filters = tableInfo?.[guid]?.[page]?.[controlId!]?.filters || {};
  if (!attrs) {
    return [];
  }

  const cols = attrs
    .filter((col) => (col as VisibleColumnType).visible !== '0' && col.width)
    .map((col) => {
      const colTitle =
        col.columnName ||
        (col.propName?.includes('$') ? col.propName.replace('$', '.') : col.propName);
      const column = columns.find((column) => column.dataIndex == col.propName);
      const title = getMessage(colTitle);
      const _align = col?.align || align;
      const changeAlign = _align !== 'left' && col.sorter === 'on';
      return {
        title: () => {
          return (
            <span title={title}>
              <TextWidget>{colTitle}</TextWidget>
            </span>
          );
        },
        dataIndex: col.propName,
        width: column?.width ? column.width : col.width,
        sorter: col.sorter === 'on',
        filter: col.filter === 'on',
        filteredValue: col.filter === 'on' && filters[col.propName] ? filters[col.propName] : null,
        fixed: col.fixed === 'none' ? false : col.fixed,
        ellipsis: true,
        align: _align,
        className: changeAlign ? `inbiz-table-cell cell-${_align}` : 'inbiz-table-cell',
        render: (v, record, index) => {
          let value = v;
          if (value && typeof value ==='string') {
            value = getMessage(v);
          }
          const text =
            eventsRef?.current.onColumnsFormat?.(value, record, index, col.propName) ??
            formatters.removeHtmlTag(value);
          const isString = typeof text === 'string';
          return (
            <span
              dangerouslySetInnerHTML={isString ? { __html: text } : undefined}
              title={isString ? formatters.removeHtmlTag(text) : undefined}
            >
              {!isString ? text : null}
            </span>
          );
        },
      } as ColumnType<RecordType>;
    });

  const addActions = () => {
    const actionIndex = cols.findIndex((col) => col.dataIndex === ColumnConst.actions);
    if (actionIndex > -1) {
      cols?.splice(actionIndex, 1);
    }
    const actions = (eventsRef?.current.onOperateColumnFormat?.(innerActions) ??
      innerActions) as ActionConfigType[];
    const leftActions = actions?.map((ele) => {
      return {
        ...ele,
        ...hasAuth(
          {
            table: [{ ...ele, operationType: ele.actionType }],
            auth: auth,
          },
          ele.actionType,
          inbiz?.auth,
        ),
      };
    });
    const leftAuthActions = leftActions?.filter((ele) => ele.auth);
    const actionCol: ColumnType<RecordType> = {
      title: getMessage('Table.operate'),
      dataIndex: ColumnConst.actions,
      width: formItems?.actionColumnWidth || 200,
      fixed: formItems?.fixedActionColumn === 'none' ? false : formItems?.fixedActionColumn,
      className: 'actions inbiz-table-cell',
      ellipsis: true,
      align: align,
      render: (_: any, row: any, index) => {
        let cacheActions: ActionConfigType[] = [];
        if (row.isdeleted) {
          cacheActions = leftAuthActions.filter((action) => action.actionType !== 'del');
        } else {
          cacheActions = leftAuthActions;
        }
        const ActionsList =
          eventsRef?.current?.onOperateFormat?.(row, index, JSON.parse(JSON.stringify(cacheActions))) || cacheActions;
        if (typeof ActionsList === 'function') {
          return <ActionsList row={row} index={index} actions={actions} emit={emit} />;
        }
        if (typeof ActionsList === 'string') {
          return ActionsList;
        }
        return (
          <div style={{ height: 22, overflow: 'hidden' }}>
            <Actions
              data={row}
              actions={ActionsList}
              displayQty={99}
              style={{ justifyContent: align }}
              isTableActions={true}
              index={index}
            />
          </div>
        );
      },
    };
    if (leftAuthActions && leftAuthActions.length > 0 && viewMode != 'look') {
      formItems?.fixedActionColumn === 'left' ? cols?.unshift(actionCol) : cols?.push(actionCol);
    }
  };

  const formatLineNumber = () => {
    const removeLineNumber = () => {
      return cols.filter((col) => col.dataIndex !== ColumnConst.index);
    };
    const addLineNumber = () => {
      const { current, pageSize } = searchRef.current.pageInfo;
      cols.unshift({
        title: () => {
          return (
            <span title={getMessage('Table.serialNumber')}>
              <TextWidget>Table.serialNumber</TextWidget>
            </span>
          );
        },
        width: 50,
        dataIndex: ColumnConst.index,
        fixed: 'left',
        align: align,
        className: 'index inbiz-table-cell',
        render: (text, record, rowIdx) => {
          record[ColumnConst.index] = current && rowIdx + 1 + (current - 1) * (pageSize || 10);
          return record[ColumnConst.index];
        }
      });
    };
    return showLineNumber ? addLineNumber() : removeLineNumber();
  };

  formatLineNumber();
  
  addActions();

  const getFilterProps = (): ColumnType<RecordType> => {
    const getFilters = () => {
      if (!actions?.find((action) => action.actionType === ActionEnum.customColumn)) {
        return;
      }
      return attrs.reduce((filters: { value: any; label: any }[], attr) => {
        if ((attr as VisibleColumnType).visible === '0' || !attr.width || (attr.fixed && attr.fixed !== 'none')) {
          return filters;
        }
        const label =
          attr.columnName ||
          (attr.propName?.includes('$') ? attr.propName.split('$').pop() : attr.propName);
        filters.push({
          label: label,
          value: attr.propName,
        });
        return filters;
      }, []);
    };
    let filters = getFilters();
    const defaultFilteredValue = filters?.map((filter) => filter.value);

    const hasfilter = actions.filter((ele) => ele.actionType === 'customColumn')[0] || {};
    const filterAuth = hasAuth(
      {
        table: [{ ...hasfilter, operationType: hasfilter.actionType }],
        auth: auth,
      },
      hasfilter.actionType,
      inbiz?.auth,
    );
    const DragHandle = SortableHandle(() => <MenuOutlined style={{ display: 'flex', alignItems: 'center', cursor: 'move', color: '#999' }} />);
    const SortContainer = SortableContainer(({ children }) => {
      return <Checkbox.Group>{children}</Checkbox.Group>;
    }) as any;
    const SortableItem = SortableElement(({ filter }) => (
      <Row>
        <Checkbox value={filter.value}>
          <TextWidget>{filter.label}</TextWidget>
        </Checkbox>
        <DragHandle />
      </Row>
    )) as any;
    sortFiltersRef.current = [...sortFilters?.length ? sortFilters : filters || []];
    const onSortEnd = ({oldIndex, newIndex}: {oldIndex: number, newIndex: number}) => {
      const _filters: any = arrayMoveImmutable(sortFiltersRef.current, oldIndex, newIndex);
      setSortFilters(_filters);
    };
    return filterAuth.auth
      ? {
        filterDropdown: filters
          ? ({ selectedKeys, setSelectedKeys, confirm }) => {
            return (
              <Space direction="vertical" className="inbiz-table-custom-columns">
                <SortContainer onSortEnd={onSortEnd} useDragHandle>
                  <Checkbox.Group
                    value={selectedKeys}
                    onChange={(value) => setSelectedKeys(value as React.Key[])}
                  >
                    {sortFiltersRef.current?.map((filter,index) => (
                      <SortableItem key={filter.value} index={index} filter={filter} />
                    ))}
                  </Checkbox.Group>
                </SortContainer>
                <Space size="large">
                  <Button
                    type="link"
                    onClick={() => {
                      setSelectedKeys(
                        Array.isArray(defaultFilteredValue) ? defaultFilteredValue : [],
                      );
                      setSortFilters([]);
                      sortColumnsRef.current = [];
                      confirm({ closeDropdown: true });
                    }}
                    size="small"
                  >
                    {columnResetName ? (
                      columnResetName
                    ) : (
                      <TextWidget>Table.repossess</TextWidget>
                    )}
                  </Button>
                  <Button
                    size="small"
                    type="primary"
                    onClick={() => {
                      if (sortFilters.length) {
                        changeViewRef.current = true;
                        setChangeView(!changeView);
                      }
                      confirm({ closeDropdown: true });
                    }}
                  >
                    <TextWidget>Table.confirm</TextWidget>
                  </Button>
                </Space>
              </Space>
            );
          }
          : undefined,
        defaultFilteredValue,
        filterIcon: filters && (
          <InbizIcon type="icon-ic-setting" operationflag={filterAuth.operationflag} style={hasfilter?.buttonColor ? { color: hasfilter.buttonColor } : {}} />
        ),
      }
      : {};
  };

  const fixedLeft = cols.filter((col) => col.fixed === 'left');
  const rightLeft = cols.filter((col) => col.fixed === 'right');
  const unfixed = cols.filter((col) => !col.fixed);
  let all = [...fixedLeft, ...unfixed, ...rightLeft];
  const index = all.findIndex((item) => item.dataIndex == 'inBizTableActions');
  // 判断是否有操作列，有就在操作列上面添加自定义列，没有就添加在表格的最后一列
  if (index !== -1) {
    all[index] = {
      ...all[index],
      ...getFilterProps(),
    };
  }
  let _columns: any = all.map((ele) => ({
    ...ele,
    showSorterTooltip: false,
    title: ({ sortOrder, sortColumn, filters }) => {
      const titleEle = typeof ele.title === 'string' ? ele.title : ele.title?.();
      return (
        <div className="antd-self-sort-wrap">
          {titleEle}
          {ele.sorter && SortNode(sortOrder, ele.dataIndex === sortColumn?.dataIndex)}
        </div>
      );
    },
  }));
  // 如果拖动了排序，并且是点击了确定按钮，则需要调整columns的顺序
  if (changeViewRef.current && sortFilters.length) {
    const _sortFilters = [...sortFilters];
    const data: any = [];
    for (let i = 0; i < all.length; i++) {
      const item = all[i];
      if (data.length && data.findIndex(filter => filter.dataIndex == item.dataIndex) !== -1) {
        continue;
      }
      if (_sortFilters.every(filter => filter.value !== item.dataIndex)) {
        data.push(item);
      } else {
        _sortFilters.forEach(filter => {
          const current = all.find(item => item.dataIndex === filter?.value);
          data.push(current);
        })
      }
    }
    sortColumnsRef.current = data;
  }
  changeViewRef.current = false;
  return sortColumnsRef.current.length ? sortColumnsRef.current : _columns;
}

/**
 * 格式化卡片打印表格配置
 * @param config 配置项
 * @returns 格式化后的配置项
 */
export function useFormatCardColumns(config: { [key: string]: any }) {
  const { title, dataItems } = config;
  let columns: any = [];
  if (Object.keys(title).length > 0) {
    columns.push({
      title: title.label,
      dataIndex: title.propName,
      key: title.propName,
    });
  }
  if (dataItems.length > 0) {
    dataItems.forEach((data: { label: string; propName: string }) => {
      columns.push({
        title: data.label,
        dataIndex: data.propName,
        key: data.propName,
      });
    });
  }
  return columns;
}

/**
 * 格式化卡片打印表格配置
 * @param config 当前模板配置项
 * @param value 卡片配置
 * @param onChange 操作回调
 * @returns 格式化后的配置项
 */
export function useFormatCardAttrColumns(
  columns: { [key: string]: any }[],
  value: any,
  onChange: (param: any) => void,
  callback: (param: any) => void,
  ref?: any,
) {
  const cacheColumns = columns.map((column) => {
    if (column.dataIndex === 'placeText') {
      column.render = (text: string, record: any) => {
        if (!record?.children && !record?.typeValue) {
          return (
            <>
              <span>{text}</span>
              <div
                className="inbiz-card-placetext-del"
                title={getMessage('Table.button.delete')}
                onClick={() => {
                  const attrsValues = [...value?.tableValues?.['attrs']];
                  for (let i = 0; i < attrsValues.length; i++) {
                    if (attrsValues[i].id === record.id) {
                      attrsValues.splice(i, 1);
                      break;
                    }
                    // 如果存在children 则继续查找
                    if (attrsValues[i]?.children && attrsValues[i]?.children.length > 0) {
                      const index = attrsValues[i].children.findIndex(
                        (child: any) => child.id === record.id,
                      );
                      if (index !== -1) {
                        attrsValues[i].children.splice(index, 1);
                        if (!attrsValues[i].children.length) {
                          callback([record?.id]);
                        }
                        break;
                      }
                    }
                  }
                  onChange({
                    ...value,
                    tableValues: {
                      ...value.tableValues,
                      attrs: attrsValues,
                    },
                  });
                }}
              >
                <InbizIcon type="icon-ic-tree-huishouzhan" />
              </div>
            </>
          );
        }
        return record?.typeValue === 'array' ? (
          <>
            <span>{text}</span>
            <span
              className="inbiz-card-placetext-add"
              title={getMessage('Table.button.addTo')}
              onClick={() => {
                const newAttrsValues = ref.current?.getDataSource();
                const attrsValues = newAttrsValues.map((item: any) => {
                  let obj = {
                    id: uuid(5, 5),
                    placeKey: '',
                    placeText: '',
                    label: '',
                    propName: '',
                  };
                  if (record.id === item.id) {
                    item['children'] = item['children'] ? [...item['children']] : [];
                    item['children'].push(obj);
                  }
                  return item;
                });
                callback(record.id);
                onChange({
                  ...value,
                  tableValues: {
                    ...value.tableValues,
                    attrs: attrsValues,
                  },
                });
              }}
            >
              <InbizIcon type="icon-ic-tianjia-moren" />
            </span>
          </>
        ) : (
          <span>{text}</span>
        );
      };
    }
    return column;
  });
  return cacheColumns;
}

export const useGetChild = () => {
  const { inbiz, controlId } = useContext(InBizTableCtx);
  const childRef = useRef<Array<string>>([]);
  useEffect(() => {
    //@ts-ignore
    const fields = inbiz?.getFields() ?? [];
    fields.forEach((ele: any) => {
      if (ele.componentType == 'Table' && ele.componentProps.selectComponent === controlId) {
        childRef.current.push(ele.componentProps.controlId);
      }
    });
  }, []);

  return childRef.current;
};

/**
 * 更新数据，如果当前页不是第一页，且后端查询无数据时，继续请求前一页的数据
 */
export const useRefreshData = (fetchData: () => []) => {
  const { searchRef } = useContext(InBizTableRefCtx);
  // const { fetchData } = useFetchData();
  return useCallback(async () => {
    const {
      current: {
        pageInfo: { current },
      },
    } = searchRef;
    let res: [] = await fetchData();
    while (!res?.length && current > 1) {
      searchRef.current.pageInfo.current = searchRef.current.pageInfo.current - 1;
      res = await fetchData();
    }
  }, []);
};

/**
 * 缓存表格视图和列宽
 */
export const setTableStorage = (params: {
  inbiz?: IPageInbiz | undefined;
  controlId: string;
  nexTtype?: string;
  tableTagStatus?: string;
  mergedColumns?: ColumnsType<RecordType>;
  filterValues?: Record<string, FilterValue | null>;
}) => {
  const { controlId, nexTtype, mergedColumns, filterValues, tableTagStatus, inbiz } = params;
  const tableStorage = localStorage.getItem('inbiz-table');
  const guid = inbiz?.appInfo?.userInfo.guid;
  const page = inbiz?.pageId;
  let tableInfo = tableStorage && JSON.parse(tableStorage);
  if (filterValues) {
    delete filterValues[ColumnConst.actions];
  }
  if (tableInfo?.[guid]) {
    if (tableInfo?.[guid]?.[page]) {
      if (tableInfo?.[guid]?.[page]?.[controlId]) {
        if (nexTtype) {
          tableInfo[guid][page][controlId] = {
            ...tableInfo[guid][page][controlId],
            type: nexTtype,
          };
        } else if (filterValues) {
          tableInfo[guid][page][controlId] = {
            ...tableInfo[guid][page][controlId],
            // filters: filterValues,
          };
        } else if (tableTagStatus) {
          tableInfo[guid][page][controlId] = {
            ...tableInfo[guid][page][controlId],
            tagStatus: tableTagStatus,
          };
        } else {
          tableInfo[guid][page][controlId] = {
            ...tableInfo[guid][page][controlId],
            columns: mergedColumns,
          };
        }
      } else {
        tableInfo = {
          ...tableInfo,
          [guid]: {
            [page]: {
              ...tableInfo[guid][page],
              [controlId]: {
                type: nexTtype,
                columns: mergedColumns,
                tagStatus: tableTagStatus,
                // filters: filterValues,
              },
            },
          },
        };
      }
    } else {
      tableInfo = {
        ...tableInfo,
        [guid]: {
          ...tableInfo[guid],
          [page]: {
            [controlId]: {
              type: nexTtype,
              columns: mergedColumns,
              tagStatus: tableTagStatus,
              // filters: filterValues,
            },
          },
        },
      };
    }
  } else {
    tableInfo = {
      ...tableInfo,
      [guid]: {
        [page]: {
          [controlId]: {
            type: nexTtype,
            columns: mergedColumns,
            tagStatus: tableTagStatus,
            // filters: filterValues,
          },
        },
      },
    };
  }
  localStorage.setItem('inbiz-table', JSON.stringify(tableInfo));
};

export const getTableStorage = () => {
  const tableStorage = localStorage.getItem('inbiz-table');
  return tableStorage && JSON.parse(tableStorage);
};

export const useSearchTagsData = () => {
  const { inbiz } = useContext(InBizTableCtx);
  const { tableTopRef } = useContext(InBizTableRefCtx);
  const [tagData, setTagData] = useState({});
  const fetchTagData = useCallback(() => {
    const appInfo = inbiz?.appInfo;
    const params = {
      appId: appInfo?.appId || '',
      siteOutId: appInfo?.OutId || '',
      pageOutId: inbiz?.pageId,
    };
    tableApi.getTableSearch(params).then((res) => {
      tableTopRef.current = {
        ...tableTopRef.current,
        data: res?.status === 204 || res?.status === 200 ? {} : res,
      };
      setTagData(res);
    });
  }, []);
  return {
    tagData,
    fetchTagData,
  };
};
